package com.tengju.bff.interfaces.covercharge.controller.admin;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.idanchuang.component.base.JsonResult;
import com.idanchuang.component.config.apollo.util.ConfigUtil;
import com.idanchuang.component.redis.util.DRedisLocks;
import com.idanchuang.component.redis.util.RedisUtil;
import com.tengju.bff.interfaces.covercharge.constant.BizConstants;
import com.tengju.bff.interfaces.covercharge.constant.CoverChargeErrorCode;
import com.tengju.bff.interfaces.covercharge.entity.vo.ServiceWithdarwCycleAddQueryVO;
import com.tengju.bff.interfaces.covercharge.entity.vo.ServiceWithdarwCycleAddVO;
import com.tengju.bff.interfaces.covercharge.entity.vo.CycleAddCheckTaskResult;
import com.tengju.bff.interfaces.covercharge.service.IServiceWithdarwCycleAddService;
import com.tengju.bff.interfaces.covercharge.util.DateTimeUtils;
import com.tengju.bff.interfaces.shared.ApiResponse;
import com.tengju.bff.interfaces.shared.servlet.ManageEntrance;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.Objects;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author wangcheng
 * @date 2020/10/14
 * @description 服务费提现金额核对
 */
@Slf4j
@RestController
@RequestMapping("/manage/cycleAddCheck")
@Api(value = "cycleAddCheck", tags = "服务费提现金额核对")
@ManageEntrance
public class AdminServiceCycleAddCheckController {

    @Autowired
    private IServiceWithdarwCycleAddService serviceWithdarwCycleAddService;

    @Resource
    private ThreadPoolExecutor threadPoolExecutor;

    @PostMapping("/getAllTotal")
    @ApiOperation(value = "服务费周期提现总金额")
    @RequiresRoles("sso")
    public ApiResponse<ServiceWithdarwCycleAddVO> getAllTotal(@RequestBody ServiceWithdarwCycleAddQueryVO serviceWithdarwCycleAddQueryVO){
        if (StringUtils.isEmpty(serviceWithdarwCycleAddQueryVO.getCycleDate())) {
            return ApiResponse.newFailure(CoverChargeErrorCode.PARAM_ERROR.getCode(), "提现周期不能为空");
        }
        Assert.hasText(serviceWithdarwCycleAddQueryVO.getApprovers(), "操作人不能为空");

        String cycleDay = ConfigUtil.getConfig().getString("withdraw.cycle.day", "10");
        String startDateStr = DateTimeUtils.parseDateAsString(
                DateTimeUtils.addMonths(DateUtil.parse(serviceWithdarwCycleAddQueryVO.getCycleDate(), DateTimeUtils.MONTH_FORMAT), -1),
                DateTimeUtils.MONTH_FORMAT)
                + "-" + (Integer.parseInt(cycleDay) + 1) + " 00:00:00";

        String endDateStr = DateTimeUtils.parseDateAsString(
                DateUtil.parse(serviceWithdarwCycleAddQueryVO.getCycleDate(), DateTimeUtils.MONTH_FORMAT),
                DateTimeUtils.MONTH_FORMAT)
                + "-" + cycleDay + " 23:59:59";

        //判断该周期是不是已经完成了
        Date nowDate = new Date();
        Date endDateChekc= DateUtil.parseDateTime(endDateStr);
        if(endDateChekc.compareTo(nowDate) >= 0){
            return ApiResponse.newFailure(CoverChargeErrorCode.PARAM_ERROR.getCode(), serviceWithdarwCycleAddQueryVO.getCycleDate()+"周期没有结束，不能进行校对！");
        }

        serviceWithdarwCycleAddQueryVO.setStartDateStr(startDateStr);
        serviceWithdarwCycleAddQueryVO.setEndDateStr(endDateStr);

        return DRedisLocks.runWithLock(BizConstants.SERVICE_WITHDRAW_CYCLE_ADD_CHECK_LOG + serviceWithdarwCycleAddQueryVO.getCycleDate(), 1000, () -> {
            try {
                ServiceWithdarwCycleAddVO serviceWithdarwCycleAddVO=new ServiceWithdarwCycleAddVO();

                //异步线程处理
                threadPoolExecutor.execute(() -> {
                    //获取key
                    String lockKey = BizConstants.SERVICE_WITHDRAW_CYCLE_ADD_CHECK_LOG_KEY + serviceWithdarwCycleAddQueryVO.getCycleDate();
                    String cycleAddCheck = RedisUtil.getInstance().get(lockKey);
                    if (!StringUtils.isEmpty(cycleAddCheck)) {
                        return ;
                    }
                    //存入key,5000毫秒。还有setObjIfAbsent,TimeUnit.MILLISECONDS为过期时间单位
                    if(!RedisUtil.getInstance().setIfAbsent(lockKey, serviceWithdarwCycleAddQueryVO.getCycleDate(), 30000, TimeUnit.MILLISECONDS)){
                        return ;
                    }

                    //获取总数
                    Integer allSize=serviceWithdarwCycleAddService.sumTotal(serviceWithdarwCycleAddQueryVO);
                    serviceWithdarwCycleAddQueryVO.setNum(allSize);
                    //周期标识
                    String taskSey=serviceWithdarwCycleAddQueryVO.getCycleDate()+"_周期打款校验_"+serviceWithdarwCycleAddQueryVO.getApprovers();

                    CycleAddCheckTaskResult taskResult=serviceWithdarwCycleAddService.cycleAddCheckCreateTask(allSize, taskSey,serviceWithdarwCycleAddQueryVO.getApprovers());
                    if (taskResult.isTaskResult()){
                        try {
                            serviceWithdarwCycleAddQueryVO.setTaskNo(taskResult.getTaskNo());
                            serviceWithdarwCycleAddService.getAllTotal(serviceWithdarwCycleAddQueryVO);

                        } catch (Exception e) {
                            log.error("[服务费后台][周期校验][异步线程-导入打款数据处理异常]:", e);
                            serviceWithdarwCycleAddService.updateCycleCheckTask(taskResult.getTaskNo(),3,0,allSize);
                        }
                    }
                });
                return ApiResponse.newSuccess(serviceWithdarwCycleAddVO);
            } catch (Exception e) {
                log.error("[服务费后台][周期校验][异步线程-导入打款数据处理异常]:", e);
                return ApiResponse.newFailure(CoverChargeErrorCode.PARAM_ERROR.getCode(), "周期打款失败");
            }
        });
    }

    @PostMapping("/checkErrorPage")
    @ApiOperation(value = "服务费提现金额异常数据列表")
    public ApiResponse<IPage<ServiceWithdarwCycleAddVO>> checkErrorPage(@RequestBody ServiceWithdarwCycleAddQueryVO serviceWithdarwCycleAddQueryVO){

        if (StringUtils.isEmpty(serviceWithdarwCycleAddQueryVO.getCycleDate())) {
            return ApiResponse.newFailure(CoverChargeErrorCode.PARAM_ERROR.getCode(), "提现周期不能为空");
        }
        String cycleDay = ConfigUtil.getConfig().getString("withdraw.cycle.day", "10");
        String startDateStr = DateTimeUtils.parseDateAsString(
                DateTimeUtils.addMonths(DateUtil.parse(serviceWithdarwCycleAddQueryVO.getCycleDate(), DateTimeUtils.MONTH_FORMAT), -1),
                DateTimeUtils.MONTH_FORMAT)
                + "-" + (Integer.parseInt(cycleDay) + 1) + " 00:00:00";
        String endDateStr = DateTimeUtils.parseDateAsString(
                DateUtil.parse(serviceWithdarwCycleAddQueryVO.getCycleDate(), DateTimeUtils.MONTH_FORMAT),
                DateTimeUtils.MONTH_FORMAT)
                + "-" + cycleDay + " 23:59:59";
        serviceWithdarwCycleAddQueryVO.setStartDateStr(startDateStr);
        serviceWithdarwCycleAddQueryVO.setEndDateStr(endDateStr);

        return ApiResponse.newSuccess(serviceWithdarwCycleAddService.checkErrorPage( serviceWithdarwCycleAddQueryVO));
    }
}
